
/*
 * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * Redistribution of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 
 * Redistribution in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 
 * Neither the name of Sun Microsystems, Inc. or the names of
 * contributors may be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * 
 * This software is provided "AS IS," without a warranty of any kind.
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 */
#define _POSIX_C_SOURCE 1

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/time.h>

#include "led.h"

#define IPMI_BMC_CHANNEL		0xf
#define IPMI_SYSTEM_INTERFACE_ADDR_TYPE	0x0c

struct ipmi_msg {
	unsigned char netfn;
	unsigned char cmd;
	unsigned short data_len;
	unsigned char *data;
};

struct ipmi_req {
	unsigned char *addr;
	unsigned int addr_len;
	long msgid;
	struct ipmi_msg msg;
};

struct ipmi_system_interface_addr {
	int addr_type;
	short channel;
	unsigned char lun;
};

#define IPMI_IOC_MAGIC			'i'
#define IPMICTL_SEND_COMMAND		_IOR(IPMI_IOC_MAGIC, 13, struct ipmi_req)

int fd=-1;

int led_open()
{
	fd=open("/dev/ipmi0", O_RDWR);
	if(fd<0)
	{
		printf("open ipmidev failed\n");
		return -1;
	}
	return fd;
}

void led_close()
{
	if (fd >= 0)
	{
		close(fd);
	}
}

int ledA_trigger()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=2;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x18;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledB_trigger()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=2;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x20;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledC_trigger()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=2;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x14;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledD_trigger()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=2;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x16;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int led_trigger(int index)
{
	if(index==0)
	{
		ledA_trigger();
	}
	else if(index==1)
	{
		ledB_trigger();
	}
	else if(index==2)
	{
		ledC_trigger();
	}
	else if(index==3)
	{
		ledD_trigger();
	}
	else
	{
		printf("index invalid 0-3 is ok\n");
	}
}

int ledA_on()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=1;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x18;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledB_on()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=1;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x20;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledC_on()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=1;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x14;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledD_on()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=1;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x16;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int led_on(int index)
{
	if(index==0)
	{
		ledA_on();
	}
	else if(index==1)
	{
		ledB_on();
	}
	else if(index==2)
	{
		ledC_on();
	}
	else if(index==3)
	{
		ledD_on();
	}
	else
	{
		printf("index invalid 0-3 is ok\n");
	}
}

int ledA_off()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=0;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x18;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledB_off()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=0;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x20;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledC_off()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=0;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x14;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledD_off()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=0;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x16;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int led_off(int index)
{
	if(index==0)
	{
		ledA_off();
	}
	else if(index==1)
	{
		ledB_off();
	}
	else if(index==2)
	{
		ledC_off();
	}
	else if(index==3)
	{
		ledD_off();
	}
	else
	{
		printf("index invalid 0-3 is ok\n");
	}
}
